package com.dtlaya.allutils.fileUpload.Service;

import com.dtlaya.allutils.fileUpload.config.FileUploadProperties;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;

@Service
public class FileUploadService {

    private final FileUploadProperties properties;

    @Autowired
    public FileUploadService(FileUploadProperties properties) {
        this.properties = properties;
    }

    /**
     * 上传多个文件到指定路径
     * @param files 文件数组
     * @param relativePath 相对路径（多级路径）
     * @return 上传成功的文件路径列表
     * @throws IOException 文件操作异常
     */
    public List<String> uploadFiles(MultipartFile[] files, String relativePath) throws IOException {
        // 验证和清理路径
        String safeRelativePath = sanitizePath(relativePath);
        
        // 构建完整目标路径
        Path targetDir = Paths.get(properties.getBaseDir(), safeRelativePath).toAbsolutePath().normalize();
        
        // 自动创建缺失的目录
        if (properties.isCreateMissingDirs() && !Files.exists(targetDir)) {
            Files.createDirectories(targetDir);
        }
        
        // 检查目录是否存在
        if (!Files.isDirectory(targetDir)) {
            throw new IOException("目标路径不是目录: " + targetDir);
        }
        
        // 处理每个文件
        return Arrays.stream(files)
                .filter(file -> !file.isEmpty())
                .map(file -> saveFile(file, targetDir))
                .toList();
    }

    /**
     * 保存单个文件
     * @param file 上传的文件
     * @param targetDir 目标目录
     * @return 保存的文件路径
     */
    private String saveFile(MultipartFile file, Path targetDir) {
        try {
            // 验证文件扩展名
            String originalFilename = file.getOriginalFilename();
            String extension = FilenameUtils.getExtension(originalFilename);
            
            if (!isExtensionAllowed(extension)) {
                throw new IllegalArgumentException("不允许的文件类型: " + extension);
            }
            
            // 生成唯一文件名（避免覆盖）
            String uniqueFileName = generateUniqueFileName(originalFilename);
            Path targetPath = targetDir.resolve(uniqueFileName);
            
            // 保存文件
            file.transferTo(targetPath);
            
            return targetPath.toString();
        } catch (IOException e) {
            throw new RuntimeException("文件保存失败: " + e.getMessage(), e);
        }
    }

    /**
     * 验证文件扩展名是否允许
     * @param extension 文件扩展名
     * @return 是否允许
     */
    private boolean isExtensionAllowed(String extension) {
        if (properties.getAllowExtensions() == null || properties.getAllowExtensions().isEmpty()) {
            return true;
        }
        
        return Arrays.stream(properties.getAllowExtensions().split(","))
                .anyMatch(ext -> ext.trim().equalsIgnoreCase("." + extension));
    }

    /**
     * 生成唯一文件名
     * @param originalFilename 原始文件名
     * @return 唯一文件名
     */
    private String generateUniqueFileName(String originalFilename) {
        String baseName = FilenameUtils.getBaseName(originalFilename);
        String extension = FilenameUtils.getExtension(originalFilename);
        return baseName + "_" + UUID.randomUUID() + "." + extension;
    }

    /**
     * 清理和验证路径
     * @param path 原始路径
     * @return 安全路径
     */
    private String sanitizePath(String path) {
        if (path == null || path.isEmpty()) {
            return "";
        }
        
        // 规范化路径
        String normalized = path.replace("\\", properties.getPathSeparator())
                               .replaceAll("/+", properties.getPathSeparator())
                               .trim();
        
        // 移除开头和结尾的分隔符
        if (normalized.startsWith(properties.getPathSeparator())) {
            normalized = normalized.substring(1);
        }
        if (normalized.endsWith(properties.getPathSeparator())) {
            normalized = normalized.substring(0, normalized.length() - 1);
        }
        
        // 检查路径深度
        int depth = normalized.split(properties.getPathSeparator()).length;
        if (depth > properties.getMaxDepth()) {
            throw new IllegalArgumentException("路径深度超过最大限制: " + depth + " > " + properties.getMaxDepth());
        }
        
        return normalized;
    }
}